﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using App.Core;
using App.Core.Common;
using App.Core.DataAccess;
using App.Core.Domain;
using App.Core.Domain.BaseObject;
using App.Core.Dtos;
using Omu.ValueInjecter;
using EntityFramework.Extensions;

namespace App.Services.Impls
{
    public partial class UserServiceImpl :AppServiceBase,IUserService
    {
        public async Task<OperationResult<User>> CreateUserAsync(UserDto dto)
        {
            using (var db = new Db())
            {
                if (dto.Password != dto.ConfrimPassword)
                {
                    return new OperationResult<User>() { success = false, message = "两次输入的密码不一致！" };
                }

                if (await db.User.CountAsync(u => u.UserName == dto.UserName) > 0)
                {
                    return new OperationResult<User>() { success = false, message = string.Format("用户名为【{0}】的用户已经存在！", dto.UserName) };
                }

                var user = new User();
                user.InjectFrom(dto);
                user.PasswordHash = PasswordHash.CreateHash(dto.Password);
                user.Team = await db.Team.FindAsync(dto.TeamId);
                user.Roles = new List<Role>();
                foreach (var roleId in dto.RoleId.Where(roleId => !roleId.Equals(Guid.Empty)))
                {
                    var role = await db.Role.FindAsync(roleId);
                    if (role != null) user.Roles.Add(role);
                }

                db.User.Add(user);
                var result = await db.SaveChangesAsync();

                return new OperationResult<User>() { success = result > 0,model = user};
            }
        }

        public async Task<OperationResult> UpdateUser(Guid id, UserDto dto)
        {
            using (var db = new Db())
            {
                var user = await db.User.Include("Roles").SingleAsync(u => u.Id == id);
                user.InjectFrom(dto);
                if (!string.IsNullOrEmpty(dto.Password))
                    user.PasswordHash = PasswordHash.CreateHash(dto.Password);
                user.Team = await db.Team.FindAsync(dto.TeamId);
                user.Roles.Clear();
                foreach (var roleId in dto.RoleId.Where(roleId => !roleId.Equals(Guid.Empty)))
                {
                    var role = await db.Role.FindAsync(roleId);
                    if (role != null) user.Roles.Add(role);
                }

                var result = await db.SaveChangesAsync();

                return new OperationResult(){success = result > 0};
            }
        }

        public async Task<OperationResult> ChangeUserPassword(ChangePwdDto dto)
        {
            using (var db = new Db())
            {
                var user = await db.User.FindAsync(AppSession.UserId.Value);
                if (user == null || !PasswordHash.ValidatePassword(dto.OldPassword, user.PasswordHash))
                {
                    return new OperationResult() { success = false, message = "输入的旧密码与原来的密码不一致，密码修改失败！" };
                }

                user.PasswordHash = PasswordHash.CreateHash(dto.Password);

                var result = await db.SaveChangesAsync();

                return new OperationResult() { success = result > 0, message = "密码修改成功。" };
            }
        }

        public List<Team> GeTeams(Expression<Func<Team, bool>> predicate = null)
        {
            using (var db = new Db())
            {
                return db.Team.ToList();
            }
        }

        public async Task<OperationResult<Team>> CreateTeam(TeamDto dto)
        {
            using (var db = new Db())
            {
                if (await db.Team.CountAsync(t => t.TeamName == dto.TeamName) > 0)
                {
                    return new OperationResult<Team>() { success = false, message = string.Format("名为【{0}】的组织机构已经存在！", dto.TeamName) };
                }

                var team = new Team();
                team.InjectFrom(dto);

                db.Team.Add(team);
                var result = await db.SaveChangesAsync();

                return new OperationResult<Team>() { success = result > 0, model = team };
            }
        }

        public async Task<OperationResult> UpdateTeam(Guid id, TeamDto dto)
        {
            using (var db = new Db())
            {
                var team = await db.Team.FindAsync(id);
                if (team == null)
                {
                    return new OperationResult() { success = false, message = string.Format("找不到该记录Team Id为{0}的记录",id) };
                }

                team.InjectFrom(dto);

                var result = await db.SaveChangesAsync();

                return new OperationResult() { success = result > 0 };
            }
        }

        public async Task<OperationResult> CreateLoginLog(Guid userId)
        {
            using (var db = new Db())
            {
                db.LoginLog.Add(new LoginLog()
                {
                    IpAddress = Utils.GetUserHostAddress(),
                    User = await db.User.FindAsync(userId)
                });

                var result = await db.SaveChangesAsync();

                return new OperationResult() { success = result > 0 };
            }
        }

        public async Task<User> GetUserByUserNameAsync(string userName)
        {
            using (var db = new Db())
            {
                return await db.User.Include("Roles").FirstOrDefaultAsync(s => s.UserName == userName);
            }
        }

        public User GetUserById(Guid userId)
        {
            using (var db = new Db())
            {
                return db.User.Include("Roles").Include("LoginLogs").SingleOrDefault(s => s.Id == userId);
            }
        }

        public async Task DeleteAsync(Guid[] guid)
        {
            using (var db = new Db())
            {
                var users = db.User.Include("LoginLogs").Include("Permissions").Include("Roles").Where(s => guid.Contains(s.Id)).ToList();
                db.User.RemoveRange(users);
                await db.SaveChangesAsync();
            }
        }

        public async Task DeleteTeamAsync(Guid id)
        {
            using (var db = new Db())
            {
                await db.Team.Where(s => s.Id == id).DeleteAsync();
            }
        }

        public async Task<OperationResult> ChangeUserPassword(Guid id, string newPassword)
        {
            using (var db = new Db())
            {
                var user = await db.User.FindAsync(id);
                user.PasswordHash = PasswordHash.CreateHash(newPassword);

                await db.SaveChangesAsync();

                return new OperationResult() { success = true };
            }
        }

        public async Task<OperationResult> ChangeUserOpenId(Guid id, string openId)
        {
            using (var db = new Db())
            {
                var user = await db.User.FindAsync(id);
                user.OpenId = openId;

                await db.SaveChangesAsync();

                return new OperationResult() { success = true };
            }
        }

        public OperationResult<User> CreateUser(UserDto dto)
        {
            using (var db = new Db())
            {
                if (dto.Password != dto.ConfrimPassword)
                {
                    return new OperationResult<User>() { success = false, message = "两次输入的密码不一致！" };
                }

                var user = db.User.Include("Roles").FirstOrDefault(u => u.UserName == dto.UserName);

                if (user != null)
                {
                    if (!Utils.IsWeixin())
                    {
                        return new OperationResult<User>() { success = false, message = string.Format("用户名为【{0}】的用户已经存在！", dto.UserName) };
                    }
                    else {
                        user.InjectFrom(dto);
                    }
                }
                else
                {
                    user = new User();
                    user.InjectFrom(dto);
                    user.PasswordHash = PasswordHash.CreateHash(dto.Password);
                    user.Team = db.Team.Find(dto.TeamId);
                    user.Roles = new List<Role>();
                    foreach (var roleId in dto.RoleId.Where(roleId => !roleId.Equals(Guid.Empty)))
                    {
                        var role = db.Role.Find(roleId);
                        if (role != null) user.Roles.Add(role);
                    }

                    db.User.Add(user);
                }

                var result = db.SaveChanges();

                return new OperationResult<User>() { success = result > 0, model = user };
            }
        }

        public User GetUserByOpenId(string openId)
        {
            using (var db = new Db())
            {
                return db.User.Include("Roles").SingleOrDefault(s => s.OpenId == openId);
            }
        }
    }
}
